<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Bob Website</title>
  <style>
  </style>
</head>
<body>
  <h1>Promise的使用及原理</h1>

  <h2>同步与异步</h2>
  <p>
    任务A与任务B

    同步：等待任务A完成，才执行下一个任务B

    异步：无需等待，直接任务A开始执行的时候就开始执行B。
  </p>
  <p>
    同步和异步的使用场景
  </p>

  <h2>为什么我们需要异步解决方案：</h2>
  <p>
    一般在网络请求中我们并不知道服务端啥时候返回结果，在这个等待的过程中，我们不能让页面一直卡顿或是不能操作的状态，
    这样会给用户很不好的体验感觉，我们又需要在服务端返回结果的时候来进行相应的操作或是数据更新。
  </p>

  <h2>传统解决方案回调</h2>
  <p></p>

  <h2>ES6的Promise</h2>
  <p>Promise 简单说就是一个容器，里面保存着某个未来才会结束的事件（通常是一个异步操作）的结果。
    Promise共有三种状态：Pending（进行中）、Resolved（已完成）、Rejected（已失败），只有异步操作的结果才能
    决定Promise的状态</p>
</body>

<script>
  function fetchDate(callback) {
    setTimeout(function () {
      console.log('异步请求成功');
      callback && callback('这是异步的结果');
    }, 2000);
  }

  // fetchDate(function (res) {
  //   console.log(res);
  //   // B、C
  //   fetchDate(function () {
  //     fetchDate(function () {
  //
  //     })
  //   })
  // });

  // Promise
  // let p1 = new Promise(function (resolve, reject) {
  //   setTimeout(function () {
  //     resolve('这是resolve，成功');
  //   }, 1000);
  // });
  //
  // p1.then((res) => {
  //   // 异步成功
  //   console.log('then resolve' + res);
  // }, (err) => {
  //   // 异步失败
  //   console.log('then reject' + err);
  // });


  // Promise
  const PENDING = 'pending';
  const RESOLVE = 'resolve';
  const REJECT = 'reject';

  function Promise(executor) {
    const $this = this;

    $this.status = PENDING;
    $this.responseContent = '';

    function resolve(res) {
      // 状态凝固
      if ($this.status === PENDING) {
        $this.status = RESOLVE;
        $this.responseContent = res;

        // 执行用户的成功
        $this.success.map(cb => {
          cb && cb(res);
        });
      }
    }

    function reject(err) {
      if ($this.status === PENDING) {
        $this.status = REJECT;
        $this.responseContent = err;

        // 执行用户的成功
        $this.fail.map(cb => {
          cb && cb(err);
        });
      }
    }

    try {
      executor(resolve, reject);
    } catch (e) {
      reject(e);
    }
  }

  Promise.prototype.then = function (success, fail) {
    const $this = this;

    $this.success = [];
    $this.fail = [];

    $this.success.push(success);
    $this.fail.push(fail);
  }

  let p1 = new Promise(function (resolve, reject) {
    setTimeout(function () {
      reject('这是reject，失败');
    }, 1000);
  });

  p1.then((res) => {
    // 异步成功
    console.log('then resolve' + res);
  }, (err) => {
    // 异步失败
    console.log('then reject' + err);
  });


  /**
   * 1、同步和异步
   * 2、回调
   * 3、异步语法的最终目的：使得异步看起来更像同步
   * 4、async await
   * */


</script>
</html>
